<template>
    <div>
      <a-card>
        <title-name>
          <div class="title-wrapper">
            <span v-if="businessType === '0'">上月逾期未完成节点</span>
            <span v-else-if="businessType === '1'">本月计划</span>
            <span v-else-if="businessType === '2'">下月重点计划</span>
            <template v-if="isDetail">
              <a-button
                type="primary"
                icon="unordered-list"
                :ghost="!viewMode"
                :disabled="loading"
                @click="changeViewMode(true)"
              >
                平铺视图
              </a-button>
              <a-button
                type="primary"
                :ghost="viewMode"
                :disabled="loading"
                @click="changeViewMode(false)"
              >
                <BaseSvgIcon
                  class="icon-item"
                  icon="tree"
                />
                树状视图
              </a-button>
            </template>
          </div>
        </title-name>
        <div
          v-if="isDetail ? !viewMode : true"
          class="btn-wrapper"
        >
          <template v-if="!isAudit && !isDetail">
            <a-button
              type="primary"
              :disabled="notSelectRow || selectRow.type===1 || isDetail || loading"
              @click="handleCreateSiblingWorkPack"
            >
              新增同级阶段/类别
            </a-button>
            <a-button
              type="primary"
              :disabled="notSelectRow || selectRow.type === 1 || isDetail || loading"
              @click="handleCreateWorkPack"
            >
              新增下级阶段/类别
            </a-button>
            <a-button
              type="primary"
              :disabled="notSelectRow || isDetail || loading"
              @click="handleCreateWork"
            >
              新增业务事项
            </a-button>
            <a-button
              type="primary"
              :disabled="notSelectRow || selectRow.isUp === false ||isDetail || loading"
              @click="handleMoveUp"
            >
              上移
            </a-button>
            <a-button
              type="primary"
              :disabled="notSelectRow || selectRow.isDown === false || isDetail || loading"
              @click="handleMoveDown"
            >
              下移
            </a-button>
            <a-button
              type="primary"
              :disabled="notSelectRow || isDetail || selectRow.isRootOneNode || selectRow.notDeleteOrUpdate === 1 || loading"
              @click="handleRemove"
            >
              删除
            </a-button>
          </template>
          <a-button
            type="primary"
            :disabled="loading"
            @click="allTreeExpansion"
          >
            展开全部
          </a-button>
          <a-button
            type="primary"
            :disabled="loading"
            @click="$refs.table.clearTreeExpand()"
          >
            收起全部
          </a-button>
          <a-button
            type="primary"
            :disabled="loading"
            @click="loadData"
          >
            手动刷新
          </a-button>
        </div>
        <div class="pub-table-select-count">
          <a-icon
            type="info-circle"
            theme="twoTone"
          />
          <span>
            项目：<span class="totalNum">{{ projectName }}</span>
          </span>
          <span>
            节点共 <span class="totalNum">{{ tableInfo.nodeCount }}</span> 项
          </span>
          <span>
            一级节点共 <span
              class="totalNum"
            >{{ tableInfo.oneNodeCount }}</span> 项
          </span>
          <span>
            二级节点共 <span
              class="totalNum"
            >{{ tableInfo.twoNodeCount }}</span> 项
          </span>
          <span>
            三级节点共 <span
              class="totalNum"
            >{{ tableInfo.threeNodeCount }}</span> 项
          </span>
          <span>
            周期天数 <span class="totalNum">{{ tableInfo.durationCount }}</span> 天
          </span>
          <span>
            周期间隔 <span class="totalNum">{{ tableInfo.cycleInterval }}</span>
          </span>
        </div>
        <!-- 搜索 -->
        <a-form-model
          v-if="!isAudit && isDetail"
          :model="searchForm"
          layout="inline"
          class="week-plan-view-search"
        >
          <a-form-model-item>
            <b>搜索:</b>
          </a-form-model-item>
          <a-form-model-item>
            <a-input
              v-model="searchForm.businessMatters"
              placeholder="节点名称"
              class="week-plan-view-search-width"
            />
          </a-form-model-item>
          <a-form-model-item>
            <a-select
              v-model="searchForm.controlLevel"
              placeholder="节点管控级别"
              class="week-plan-view-search-width"
              allowClear
            >
              <a-select-option
                v-for="item in controlLevelList"
                :key="item.value"
                :value="item.value"
              >
                {{ item.label }}
              </a-select-option>
            </a-select>
          </a-form-model-item>
          <a-form-model-item>
            <a-range-picker
              v-model="searchForm.planStart"
              class="week-plan-view-search-date"
              :placeholder="['计划开始时间起','计划开始时间止']"
            />
          </a-form-model-item>
          <a-form-model-item>
            <a-range-picker
              v-model="searchForm.planEnd"
              class="week-plan-view-search-date"
              :placeholder="['计划完成时间起','计划完成时间止']"
            />
          </a-form-model-item>
          <a-form-model-item>
            <a-button
              type="primary"
              :loading="loading"
              @click="loadData(true,true)"
            >
              搜索
            </a-button>
            <a-button
              :disabled="loading"
              class="ml12"
              @click="handleReset"
            >
              重置
            </a-button>
          </a-form-model-item>
        </a-form-model>
        <!-- 搜索 -->
        <a-spin :spinning="loading">
          <u-table
            ref="table"
            fixed-columns-roll
            :height="500"
            show-header-overflow
            :tree-config="viewMode && isDetail ? {} : {
              children: 'children',
              expandAll: false,
            }"
            row-id="id"
            use-virtual
            border
            class="week-plan-view-table"
            @row-click="handleRowClick"
          >
            <u-table-column
              v-for="item in columns"
              :key="item.dataIndex"
              :prop="item.dataIndex"
              :label="item.title"
              :width="item.width"
              :tree-node="item.dataIndex === 'name'"
              align="center"
            >
              <template v-slot="{ row }">
                <!-- 查看 -->
                <span
                  v-if="isDetail"
                  :title="row[item.dataIndex]"
                  class="span-ellipsis"
                >
                  <template v-if="row.type === 0">
                    <template v-if="['sortNum','statusName', 'name','businessMatters','duration','startDate','endDate'].includes(item.dataIndex)">
                      {{ row[item.dataIndex] }}
                    </template>
                    <template v-if="item.dataIndex === 'controlLevel'">
                      {{ row.controlLevelName }}
                    </template>
                  </template>
                  <template v-else>
                    <template v-if="item.dataIndex === 'controlLevel'">
                      {{ row.controlLevelName }}
                    </template>
                    <template v-else>
                      {{ row[item.dataIndex] }}
                    </template>
                  </template>
                </span>
                <!-- 查看 -->
                <!-- 编辑 -->
                <span
                  v-else
                  :title="item.dataIndex === 'directResPer' ? (row.perList ? row.perList.map(i => i.directResPerName).join('、') : row[item.dataIndex]) : ''"
                >
                  <!-- 阶段类别 -->
                  <span
                    v-if="row.type === 0"
                    class="span-ellipsis"
                  >
                    <span v-if="['sortNum','businessMatters','duration','startDate','endDate'].includes(item.dataIndex)">
                      {{ row[item.dataIndex] }}
                    </span>
                    <template v-if="item.dataIndex === 'controlLevel'">
                      {{ row.controlLevelName }}
                    </template>
                    <!-- 阶段/类别 -->
                    <BaseInput
                      v-if="item.dataIndex === 'name'"
                      v-model="row.name"
                      :placeholder="'请输入'+item.title"
                      :disabled="(row.notDeleteOrUpdate === 1 || row.isUpMontSyn) && !row.isEditWorkName"
                      @focus="saveFocusValue(item.dataIndex, row[item.dataIndex])"
                      @blur="handleUpdate(row, false, item.dataIndex)"
                    />
                    <!-- 阶段/类别 -->
                  </span>
                  <!-- 阶段类别 -->
                  <!-- 业务事项 -->
                  <template v-else>
                    <!-- 序号 -->
                    <span v-if="item.dataIndex === 'sortNum'">
                      {{ row[item.dataIndex] }}
                    </span>
                    <!-- 序号 -->
                    <!-- 业务事项 -->
                    <BaseInput
                      v-if="item.dataIndex === 'businessMatters'"
                      v-model="row.businessMatters"
                      :placeholder="'请输入'+item.title"
                      :disabled="row.notDeleteOrUpdate === 1 || row.isUpMontSyn"
                      @focus="saveFocusValue(item.dataIndex, row[item.dataIndex])"
                      @blur="handleUpdate(row, false, item.dataIndex)"
                    />
                    <!-- 业务事项 -->
                    <!-- 管控级别 -->
                    <a-select
                      v-if="item.dataIndex === 'controlLevel'"
                      v-model="row.controlLevel"
                      :placeholder="'请选择'+item.title"
                      class="width-100"
                      :disabled="row.notDeleteOrUpdate === 1 || row.isUpMontSyn"
                      @change="handleUpdate(row, false, item.dataIndex)"
                    >
                      <a-select-option
                        v-for="{value,label} in controlLevelList"
                        :key="value"
                        :value="value"
                      >
                        {{ label }}
                      </a-select-option>
                    </a-select>
                    <!-- 管控级别 -->
                    <!-- 周期(天) -->
                    <BaseInputNumber
                      v-if="item.dataIndex === 'duration'"
                      v-model="row.duration"
                      :placeholder="'请输入'+item.title"
                      :min="1"
                      :max="2000"
                      :is-int="true"
                      :disabled="true"
                    />
                    <!-- <template v-if="item.dataIndex === 'duration'">
                      {{ row[item.dataIndex] }}
                    </template> -->
                    <!-- 周期(天) -->
                    <!-- 计划开始时间 -->
                    <a-date-picker
                      v-if="item.dataIndex === 'startDate'"
                      v-model="row.startDate"
                      :allow-clear="false"
                      :placeholder="'请输入，如2023-01-01'"
                      :disabled="row.notDeleteOrUpdate === 1"
                      :open="row.startDateOpen"
                      :disabled-date="(current)=>{return startDateDisabled(current,row)}"
                      @openChange="(e)=>{row.startDateOpen = e}"
                      @change="(e)=>{handleComputeDuration(e,row,1)}"
                      :getCalendarContainer="getCalendarContainer()"
                    />
                    <!-- 计划开始时间 -->
                    <!-- 计划完成时间 -->
                    <a-date-picker
                      v-if="item.dataIndex === 'endDate'"
                      v-model="row.endDate"
                      :allow-clear="false"
                      :placeholder="'请输入，如2023-01-01'"
                      :disabled="row.notDeleteOrUpdate === 1"
                      :open="row.endDateOpen"
                      :disabled-date="(current)=>{return endDateDisabled(current,row)}"
                      @change="(e)=>{handleComputeDuration(e,row,2)}"
                      @openChange="(e)=>{row.endDateOpen = e}"
                      :getCalendarContainer="getCalendarContainer()"
                    />
                    <!-- 计划完成时间 -->
                    <!-- 完成标准 -->
                    <a-auto-complete
                      v-if="item.dataIndex === 'completeStandard'"
                      v-model="row.completeStandard"
                      :placeholder="'请选择'+item.title"
                      :data-source="completeStandardList"
                      class="width-100"
                      allow-clear
                      :filter-option="true"
                      :disabled="row.notDeleteOrUpdate === 1 || row.isUpMontSyn"
                      @change="handleCompleteStandard($event,row)"
                    />
                    <!-- 完成标准 -->
                    <!-- 验证资料 -->
                    <BaseInput
                      v-if="item.dataIndex === 'verifyFiles'"
                      v-model="row.verifyFiles"
                      :placeholder="'请输入'+item.title"
                      :disabled="row.notDeleteOrUpdate === 1 || row.isUpMontSyn"
                      @focus="saveFocusValue(item.dataIndex, row[item.dataIndex])"
                      @blur="handleUpdate(row, false, item.dataIndex)"
                    />
                    <!-- 验证资料 -->
                    <!-- 第一责任人 -->
                    <span
                      v-if="item.dataIndex === 'firstResName'"
                      class="span-btn-ellipsis"
                    >
                      <span
                        v-show="row.firstResName"
                        class="span-btn-ellipsis-text"
                      >
                        {{ row[item.dataIndex] }}
                      </span>
                      <a
                        class="span-btn-ellipsis-btn"
                        :disabled="row.notDeleteOrUpdate === 1 || row.isUpMontSyn"
                        @click="()=>{row.notDeleteOrUpdate === 1 || row.isUpMontSyn ? '' : handleFirstResNameSelect(row)}"
                      > {{ row.firstResName?'(重新选择)':'选择岗位' }} </a>
                    </span>
                    <!-- 第一责任人 -->
                    <!-- 直接责任人 -->
                    <div
                      v-if="item.dataIndex === 'directResPer'"
                      class="span-btn-ellipsis"
                    >
                      <span
                        v-show="!row.showSelect"
                        class="span-btn-ellipsis-text"
                      >
                        {{ row.perList ? row.perList.map(i => i.directResPerName).join('、') : row[item.dataIndex] }}
                      </span>
                      <a-select
                        v-show="row.showSelect"
                        :ref="'directSelect-' + row.sortNum"
                        v-model="row.directResPerList"
                        :placeholder="'请选择'+item.title"
                        mode="multiple"
                        class="span-btn-ellipsis-text"
                        @dropdownVisibleChange="dropdownVisibleChange($event, row)"
                        @change="((value)=>{handleDirectResPer(value,row)})"
                      >
                        <a-select-option
                          v-for="{employeeId,name,phone} in directlyDutyPersonList"
                          :key="employeeId"
                          :value="employeeId"
                          :data="{directResPerName:name}"
                        >
                          <a-tooltip :placement="'topLeft'">
                            <template slot="title">
                              {{ phone }}
                            </template>
                            {{ name }}
                          </a-tooltip>
                        </a-select-option>
                      </a-select>
                      <a
                        class="span-btn-ellipsis-btn"
                        :disabled="row.notDeleteOrUpdate === 1 || row.isUpMontSyn"
                        @click="()=>{row.notDeleteOrUpdate === 1 || row.isUpMontSyn ? '' : handleDirectResPerSelect(row,true)}"
                      >(点击选择)</a>
                    </div>
                    <!-- 直接责任人 -->
                  </template>
                  <!-- 业务事项 -->
                </span>
                <!-- 编辑 -->
              </template>
            </u-table-column>
          </u-table>
        </a-spin>
      </a-card>
      <!-- 选择第一责任人 -->
      <modal
        v-if="firstResNameVisible"
        :id="firstResNameData.id"
        :form-data="firstResNameData.formData"
        :org-query="firstResNameData.orgQuery"
        :screening="true"
        :visible="true"
        @handleCancelFirstRes="firstResNameVisible = false"
        @handleOk="handleFirstResName"
      />
      <!-- 选择第一责任人 -->
    </div>
  </template>
  <script>
  import { UTable, UTableColumn } from 'umy-ui'
  import { columnsDetail, controlLevelList, completeStandardList, verifyFilesList } from '../model'
  import monthPlanApi from '@/api/construction/monthPlanApi'
  import { getProjects } from '@/api/construction/planInput'
  import modal from '@/components/SelectJobs'
  import Vue from 'vue'
  import { getOrganizeUserListQuick } from '@/api/commons'
  export default {
    name: 'monthPlanDetail' + Date.now(),
    props: {
      // 是否作为审批详情
      isAudit: {
        type: Boolean,
        default: false
      },
      businessType: {
        type: String,
        default: ''
      },
      rootId: {
        type: String,
        default: ''
      },
      allData: {
        type: Object,
        default: () => {}
      },
    },
    components: {
      UTable,
      UTableColumn,
      modal
    },
    data() {
      return {
        projectName: '',
        // 选中项
        selectRow: {},
        // 表格加载
        loading: false,
        // 表格信息
        tableInfo: {
          nodeCount: 0,
          oneNodeCount: 0,
          twoNodeCount: 0,
          threeNodeCount: 0,
          durationCount: 0,
          cycleInterval: 0
        },
        // 表格数据
        tableData: [],
        // 搜索表单
        searchForm: {},
        // 是否搜索
        isSearch: false,
        // 管控级别
        controlLevelList,
        // 完成标准
        completeStandardList,
        // 验证资料
        verifyFilesList,
        // 第一责任人模态框显示隐藏
        firstResNameVisible: false,
        // 第一责任人模态框数据
        firstResNameData: {
          id: '',
          formData: {
            fileList: []
          },
          orgQuery: {},
          row: {}
        },
        // 直接责任人列表
        directlyDutyPersonList: [],
        // 项目id
        projectId: this.isAudit ? this.$route.query.businessId + '' : this.$route.query.projectId + '',
        // 流程配置
        processConfig: null,
        //点击提交发送流程配置值
        setProcessConfig: null,
        // 业务id
        businessId: null,
        // 焦点值
        focusValue: {
          key: '',
          value: ''
        },
        // 视图模式,true:平铺视图,false:树状视图
        viewMode: true
      }
    },
    computed: {
      // 没有选中
      notSelectRow() {
        return Object.keys(this.selectRow).length === 0
      },
      // 是查看
      isDetail() {
        return this.$route.query.pageType === 'detail' || this.isAudit
      },
      columns() {
        let list = this.$clone(columnsDetail)
        return list
      }
    },
    watch: {
      allData: {
        handler(val) {
          if (val) {
            if (this.viewMode) {
              this.tableData = val.nodes ? val.nodes : []
            } else {
              this.tableData = val.tree ? val.tree : []
            }
            this.tableInfo = {
              nodeCount: val.nodeCount || 0, // 节点总数
              oneNodeCount: val.oneNodeCount || 0, // 一级节点
              twoNodeCount: val.twoNodeCount || 0, // 二级节点
              threeNodeCount: val.threeNodeCount || 0, // 三级节点
              durationCount: val.durationCount || 0, // 周天总数
              cycleInterval: val.cycleInterval || 0, // 周期间隔
            }
          }
          
        }
      },
      // 表格数据监听
      tableData: {
        handler(list) {
          if (this.$refs.table) {
            const setOpen = (list) => {
              for (let i = 0; i < list.length; i++) {
                // 初始化时间弹层隐藏显示(解决时间输入识别后不能自动关闭)
                list[i].startDateOpen = false
                list[i].endDateOpen = false
                if (list[i].children) {
                  setOpen(list[i].children)
                }
              }
            }
            setOpen(this.tableData)
            // 获取之前展开数据
            const expandRecords = this.$refs.table.getTreeExpandRecords()
            // 获取之前滚动高度(表格实例上的scrollTop属性，在滚动到底部时会小于真实的scrollTop值，因此直接从dom获取真实滚动高度)
            const scrollTop = this.$refs.table.tableExample().bodyWrapper.scrollTop
            const scrollLeft = this.$refs.table.tableExample().bodyWrapper.scrollLeft
            // 加载数据
            this.$refs.table.reloadData(list).then(() => {
              // 是搜索默认展开全部
              if (this.isSearch) {
                this.$refs.table.setAllTreeExpansion()
                this.isSearch = false
              } else {
                // 数据加载完成出现之后，打开之前的展开行
                expandRecords.forEach((row) => {
                  this.$refs.table.setTreeExpansion(row, true)
                })
              }
              // 还原之前滚动高度
              this.$refs.table.pagingScrollTopLeft(scrollTop + 1, scrollLeft)
              this.$nextTick(()=>{
                // 不加这一步，列表操作栏 会变形
                this.$refs.table.pagingScrollTopLeft(scrollTop, scrollLeft)
              })
            })
          }
        }
      }
    },
    async mounted() {
      this.viewMode =  this.isDetail ? true : false
      this.projectName = this.$route.query.projectName || ''
      // 获取前置数据
      this.getProjects(this.projectId)
      const userInfo = Vue.getAcloudProvider().getUserInfo()
      this.firstResNameData.id = userInfo.id
      this.getDirectlyDutyPerson()
      this.processConfig = await this.$getConfigFn('month_plan')
    },
    methods: {
    //解决滚动条覆盖日历弹框 
      getCalendarContainer() {
        return triggerNode => triggerNode.parentNode;
      },
      changeViewMode(mode) {
        // 视图模式,true:平铺视图,false:树状视图
        this.viewMode = mode
        this.loadData()
      },
      /**
       * @description: 表格行点击
       * @param {object} row 行数据
       * @param {object} column 表头对象
       * @param {event} event 事件对象
       * @return {void}
       */
      handleRowClick(row, column, event) {
        if (this.selectRow?.id === row.id) {
          // this.selectRow = {}
        } else {
          this.$set(this, 'selectRow', row)
          // 业务事项
          // if (row.type === 1) {
          //   this.getDirectlyDutyPerson(row)
          // }
        }
      },
      /**
       * @description: 获取项目部信息
       * @param {string} id 项目id
       * @return {void}
       */
      getProjects(id) {
        getProjects({ projectIds: [id] }).then((res) => {
          this.firstResNameData.orgQuery.ids = res.data[0].orgId
        })
      },
      /**
       * @description: 获取搜索参数
       * @return {Object}
       */
      getSearchParms() {
        let startDateStart = void 0,
          startDateEnd = void 0,
          endDateStart = void 0,
          endDateEnd = void 0
        if (Array.isArray(this.searchForm?.planStart) && this.searchForm.planStart.length > 0) {
          startDateStart = this.searchForm.planStart[0].format('YYYY-MM-DD')
          startDateEnd = this.searchForm.planStart[1].format('YYYY-MM-DD')
        }
        if (Array.isArray(this.searchForm?.planEnd) && this.searchForm.planEnd.length > 0) {
          endDateStart = this.searchForm.planEnd[0].format('YYYY-MM-DD')
          endDateEnd = this.searchForm.planEnd[1].format('YYYY-MM-DD')
        }
        const { businessMatters, controlLevel } = this.searchForm
        return {
          businessType: this.businessType,
          rootId: this.rootId,
          lookType: this.viewMode ? 1 : 0,
          businessMatters,
          controlLevel,
          startDateStart,
          startDateEnd,
          endDateStart,
          endDateEnd,
        }
      },
      /**
       * @description: 获取直接责任人
       * @return {void}
       */
      getDirectlyDutyPerson() {
        getOrganizeUserListQuick({ projectId: this.projectId }).then(({ code, data }) => {
          if (code === 200) {
            this.directlyDutyPersonList = data
          } else {
            this.directlyDutyPersonList = []
          }
        })
      },
      /**
       * @description: 表格数据加载方法
       * @param {boolean} isloading 是否显示加载
       * @param {boolean} isSearch 是否搜索
       * @return {Promise} 接口Promise
       */
      async loadData(isloading = true, isSearch = false) {
        try {
          if (isloading) {
            this.loading = true
          }
          if (isSearch) {
            this.isSearch = isSearch
          }
          const fun = monthPlanApi.getNodeTree
          const {
            code,
            data
          } = await fun(this.getSearchParms())
          if (code === this.SUCCESS_CODE) {
            if (data[this.businessType]) {
              const resp = data[this.businessType]
              this.tableInfo = {
                nodeCount: resp.nodeCount || 0, // 节点总数
                oneNodeCount: resp.oneNodeCount || 0, // 一级节点
                twoNodeCount: resp.twoNodeCount || 0, // 二级节点
                threeNodeCount: resp.threeNodeCount || 0, // 三级节点
                durationCount: resp.durationCount || 0, // 周天总数
                cycleInterval: resp.cycleInterval || 0, // 周期间隔
              }
              if (this.viewMode) {
                this.tableData = resp.nodes ? resp.nodes : []
              } else {
                this.tableData = resp.tree ? resp.tree : []
              }
            }
          }
        } catch (error) {
          console.log(error)
          return Promise.reject(error)
        } finally {
          if (isloading) {
            this.loading = false
          }
        }
      },
      /**
       * @description: 重置搜索
       * @return {void}
       */
      handleReset() {
        this.searchForm = {}
        this.loadData()
      },
      /**
       * @description: 新增同级阶段/类别
       * @param {void}
       * @return {void}
       */
      handleCreateSiblingWorkPack() {
        const vm = this
        this.$confirm({
          okText: '确定',
          cancelText: '取消',
          title: '确定新增同级阶段/类别?',
          onOk() {
            monthPlanApi.addnode({ selectId: vm.selectRow.id, businessType: vm.businessType, addType: '0', rootId: vm.rootId }).then(({ code }) => {
              if (code === 200) {
                vm.$message.success('新增成功')
                vm.loadData()
              }
            })
          }
        })
      },
      /**
       * @description: 新增下级阶段/类别
       * @param {void}
       * @return {void}
       */
      handleCreateWorkPack() {
        const vm = this
        this.$confirm({
          okText: '确定',
          cancelText: '取消',
          title: '确定新增下级阶段/类别?',
          onOk() {
            monthPlanApi.addnode({ selectId: vm.selectRow.id, businessType: vm.businessType, addType: '1', rootId: vm.rootId }).then(({ code }) => {
              if (code === 200) {
                vm.$message.success('新增成功')
                vm.loadData()
              }
            })
          }
        })
      },
      /**
       * @description: 新增业务事项
       * @param {void}
       * @return {void}
       */
      handleCreateWork() {
        const vm = this
        this.$confirm({
          okText: '确定',
          cancelText: '取消',
          title: '确定新增业务事项?',
          onOk() {
            if (vm.selectRow.type === 1) {
              // 新增同级业务事项
              monthPlanApi.addnode({ selectId: vm.selectRow.id, businessType: vm.businessType, addType: '2', rootId: vm.rootId }).then(({ code }) => {
                if (code === 200) {
                  vm.$message.success('新增成功')
                  vm.loadData()
                }
              })
            } else {
              // 新增下级业务事项
              monthPlanApi.addnode({ selectId: vm.selectRow.id, businessType: vm.businessType, addType: '3', rootId: vm.rootId }).then(({ code }) => {
                if (code === 200) {
                  vm.$message.success('新增成功')
                  vm.loadData()
                }
              })
            }
          }
        })
      },
      /**
       * @description: 上移
       * @param {void}
       * @return {void}
       */
      handleMoveUp() {
        monthPlanApi.moveUp({ selectedId: this.selectRow.id, rootId: this.rootId }).then(({ code }) => {
          if (code === 200) {
            this.$message.success('上移成功')
            this.loadData()
          }
        })
      },
      /**
       * @description: 下移
       * @param {void}
       * @return {void}
       */
      handleMoveDown() {
        monthPlanApi.moveDown({ selectedId: this.selectRow.id, rootId: this.rootId }).then(({ code }) => {
          if (code === 200) {
            this.$message.success('下移成功')
            this.loadData()
          }
        })
      },
      /**
       * @description: 删除
       * @param {void}
       * @return {void}
       */
      handleRemove() {
        const vm = this
        if (this.selectRow.type === 0) {
          // 删除阶段/类别
          this.$confirm({
            okText: '确定',
            cancelText: '取消',
            title: '确定删除阶段/类别?',
            onOk() {
              monthPlanApi.deleteNode({ id: vm.selectRow.id }).then(({ code }) => {
                if (code === 200) {
                  vm.$message.success('删除成功')
                  vm.loadData()
                }
              })
            }
          })
        } else {
          // 删除业务事项
          this.$confirm({
            okText: '确定',
            cancelText: '取消',
            title: '确定删除业务事项?',
            onOk() {
              monthPlanApi.deleteNode({ id: vm.selectRow.id }).then(({ code }) => {
                if (code === 200) {
                  vm.$message.success('删除成功')
                  vm.loadData()
                }
              })
            }
          })
        }
      },
      /**
       * @description: 格式化时间
       * @param {object/string} date 时间对象或字符串
       * @param {boolean} toMoment 是否转换为Moment
       * @return {object} moment时间格式
       */
      formatDate(date, toMoment = true) {
        if (date?._isAMomentObject) {
          return toMoment ? date : date.format('YYYY-MM-DD')
        } else {
          return toMoment ? this.moment(date) : date
        }
      },
      /***
        * @description: 计划开始时间 计划完成时间禁用
        * 父级 thisMonthAdd 本月新增 0 不是 1是
        * 10，上月逾期、本月计划的节点的计划开始时间、节点的计划完成时间：
        * 1）若父级的阶段/类别的计划完成时间＞本月末，则本月1日≤业务事项的“计划开始时间/计划完成时间”≤本月末；
        * 2）若本月1日≤父级的阶段/类别的计划完成时间≤本月末，则本月1日≤业务事项的“计划开始时间/计划完成时间”≤父级的计划完成时间
        * 3）若父级的阶段/类别的计划完成时间＜本月1日，则本月1日≤业务事项的“计划开始时间/计划完成时间”≤本月末
        * 4）在以上基础上，计划完成时间≥计划开始时间
        * 11，在编辑下月重点计划时：
        * 1）若父级的阶段/类别的计划完成时间＞下月末，则下月1日≤业务事项的“计划开始时间/计划完成时间”≤下月末；
        * 2）若下月1日≤父级的阶段/类别的计划完成时间≤下月末，则下月1日≤业务事项的“计划开始时间/计划完成时间”≤父级的计划完成时间
        * 3）在以上基础上，计划完成时间≥计划开始时间
        */
      controlDateDisabled(parentEndDate, parentThisMonthAdd) {
        let endMonth = null
        let startMonth = null
        let endTime = null
        if (this.businessType === '2') {
            endMonth = this.moment().add(1, "months").endOf('month').format("YYYY-MM-DD")
            startMonth = this.moment().add(1, "months").startOf('month').format("YYYY-MM-DD")
            endTime = this.moment().add(1, "months").endOf('month').format("YYYY-MM-DD")
            if (parentEndDate !== null) {
              const parentEndDateMonth = this.moment(parentEndDate).format("YYYY-MM-DD")
              // 若本月1日≤父级的阶段/类别的计划完成时间≤本月末
              if (!!!parentThisMonthAdd && parentEndDateMonth <= endMonth) {
                endTime = this.moment(parentEndDate).format("YYYY-MM-DD")
              }
            }
        } else {
          endMonth = this.moment().endOf('month').format("YYYY-MM-DD")
          startMonth = this.moment().startOf('month').format("YYYY-MM-DD")
          endTime = this.moment().endOf('month').format("YYYY-MM-DD")
          if (parentEndDate !== null) {
            const parentEndDateMonth = this.moment(parentEndDate).format("YYYY-MM-DD")
            // 若本月1日≤父级的阶段/类别的计划完成时间≤本月末
            if (!!!parentThisMonthAdd && parentEndDateMonth <= endMonth && parentEndDateMonth >= startMonth) {
              endTime = this.moment(parentEndDate).format("YYYY-MM-DD")
            }
          }
        }
        return [startMonth, endTime]
      },
       /**
       * @description: 递归查找父级 计划完成时间
       */
      checkParentEndDate(parentId) {
        let tableData = this.$clone(this.tableData)
        let endDate = null
        let thisMonthAdd = null
        const deepFn = (data) => {
          for (let i = 0;i< data.length;i++) {
            let item = data[i]
            if (item.id === parentId) {
              endDate = item.endDate
              thisMonthAdd = item.thisMonthAdd
              return false
            } else if (item.children) {
              deepFn(item.children)
            }
          }
        }
        deepFn(tableData)
        return [endDate, thisMonthAdd]
      },
      /**
       * @description: 计划开始时间禁用
       * @param {object} current 当前时间对象
       * @param {object} row 行数据
       * @return {boolean}
       */
      startDateDisabled(current, row) {
        const [parentEndDate, parentThisMonthAdd] = row.parentId ? this.checkParentEndDate(row.parentId) : null
        const allTime = this.controlDateDisabled(parentEndDate, parentThisMonthAdd)
        // 子节点开始时间<= 子节点结束时间(结束时间不存在时直接true)
        const se = row.endDate ? this.moment(current).format("YYYY-MM-DD") <= this.moment(row.endDate).format("YYYY-MM-DD") : true
        return current && !((
          this.moment(current).format("YYYY-MM-DD") >= allTime[0] &&
          this.moment(current).format("YYYY-MM-DD") <= allTime[1]
        ) && se)
      },
      /**
       * @description: 计划完成时间禁用
       * @param {object} current 当前时间对象
       * @param {object} row 行数据
       * @return {boolean}
       */
      endDateDisabled(current, row) {
        const [parentEndDate, parentThisMonthAdd] = row.parentId ? this.checkParentEndDate(row.parentId) : null
        const allTime = this.controlDateDisabled(parentEndDate, parentThisMonthAdd)
        // 子节点开始时间<= 子节点结束时间(结束时间不存在时直接true)
        const se = row.startDate ? this.moment(current).format("YYYY-MM-DD") >= this.moment(row.startDate).format("YYYY-MM-DD") : true
        return current && !((
          this.moment(current).format("YYYY-MM-DD") >= allTime[0] &&
          this.moment(current).format("YYYY-MM-DD") <= allTime[1]
        ) && se)
      },
      /**
       * @description: 计算周期
       * @param {object} row 行数据
       * @param {number} index 字段索引
       * @return {void}
       */
      handleComputeDuration(value, row, index) {
        const indexList = ['duration', 'startDate', 'endDate']
        if ((value ?? '') === '') {
          if (index > 0) {
            // 日期格式提示
            this.$message.warning('请输入正确的日期格式，如“2023-01-01')
            return false
          } else {
            this.handleUpdate(row, false, indexList[index], true)
          }
        } else {
          const { duration, startDate, endDate } = row
          // 长度不在有三个(取消周期)
          const length = [startDate, endDate].filter((el) => el ?? '' !== '').length
          // 时间周期值个等于2
          if (length === 2) {
            // 修改周期
            if (index === 0) {
              if ((duration ?? '') !== '') {
                if ((startDate ?? '') !== '') {
                  // 计算计划完成时间(三期:计划完成时间 = 计划开始时间 + (周期 - 1))
                  row.endDate = this.formatDate(startDate)
                    .clone()
                    .add(duration - 1, 'days')
                } else {
                  // 计算计划开始时间(三期:计划开始时间 = 计划完成时间 - (周期 - 1))
                  row.startDate = this.formatDate(endDate)
                    .clone()
                    .subtract(duration + 1, 'days')
                }
              }
            }
            // 修改计划开始时间
            if (index === 1) {
              if ((startDate ?? '') !== '') {
                if ((endDate ?? '') !== '') {
                  // 计算周期(三期:周期=(计划完成时间-计划开始时间) + 1)
                  row.duration = this.formatDate(endDate).diff(this.formatDate(startDate), 'days') + 1 || void 0
                } else {
                  // 计算计划完成时间(三期:计划完成时间 = 计划开始时间 + (周期 - 1))
                  row.endDate = this.formatDate(startDate)
                    .clone()
                    .add(duration - 1, 'days')
                }
              }
            }
            // 修改计划完成时间
            if (index === 2) {
              if ((endDate ?? '') !== '') {
                if ((startDate ?? '') !== '') {
                  if (this.moment(endDate) < this.moment(row.startDate).startOf('day')) {
                    this.$message.warning('计划完成时间不能早于计划开始时间')
                  } else {
                    // 计算周期(三期:周期=(计划完成时间-计划开始时间) + 1)
                    row.duration = this.formatDate(endDate).diff(this.formatDate(startDate), 'days') + 1 || void 0
                  }
                } else {
                  // 计算计划开始时间(三期:计划开始时间 = 计划完成时间 - (周期 - 1))
                  row.startDate = this.formatDate(endDate)
                    .clone()
                    .subtract(duration + 1, 'days')
                }
              }
            }
          }
          // 时间周期值个等于3
          if (length === 3) {
            // 修改周期或者修改计划开始时间
            if (index === 0 || index === 1) {
              // 计算计划完成时间(三期:计划完成时间 = 计划开始时间 + (周期 - 1))
              row.endDate = this.formatDate(startDate)
                .clone()
                .add(duration - 1, 'days')
            }
            // 修改计划完成时间
            if (index === 2) {
              // 计算周期(三期:周期=(计划完成时间-计划开始时间) + 1)
              row.duration = this.formatDate(endDate).diff(this.formatDate(startDate), 'days') + 1 || void 0
            }
          }
          // 结合open、openChange解决时间选择器不能在输入后自动关闭的问题
          if (index === 1 || index === 2 || index === 3 || index === 4) {
            row.startDateOpen = false
            row.endDateOpen = false
          }
          this.handleUpdate(row, false, indexList[index], true)
        }
      },
      /**
       * @description: 完成标准带出验证资料
       * @param {string} value 完成标准值
       * @param {object} row 行数据
       * @return {void}
       */
      handleCompleteStandard(value, row) {
        const index = this.completeStandardList.findIndex((el) => el === value)
        if (index >= 0) {
          row.verifyFiles = this.verifyFilesList[index]
        }
        this.handleUpdate(row, false, 'completeStandard')
      },
      /**
       * @description: 直接责任人下拉展开收起
       * @param {boolean} visible 展开收起
       * @param {object} row 行数据
       * @return {void}
       */
      dropdownVisibleChange(visible, row) {
        if (!visible) {
          this.handleDirectResPerSelect(row, false)
        }
      },
      /**
       * @description: 直接责任人改变
       * @param {object} value 选中项
       * @param {object} row 行数据
       * @return {void}
       */
      handleDirectResPer(value, row) {
        row.perList = this.directlyDutyPersonList
          .filter((item) => value.includes(item.employeeId))
          .map((el) => {
            return {
              directResPerId: el.employeeId,
              directResPerName: el.name,
            }
          })
        this.handleUpdate(row, false, 'perList')
      },
      /**
       * @description: 直接责任人选择
       * @param {object} row 行数据
       * @return {void}
       */
      handleDirectResPerSelect(row, isShow) {
        this.$set(row, 'showSelect', isShow)
        if (row.showSelect) {
          this.$refs[`directSelect-${row.sortNum}`][0].$el.click()
        }
      },
      /**
       * @description: 递归查找修改阶段/类别
       * @param {array} list
       * @param {string} id
       * @param {string} name
       * @return {void}
       */
      updateName(list, id, name) {
        for (let i = 0; i < list.length; i++) {
          if (list[i].id === id) {
            list[i].name = name
            return false
          }
          if (Array.isArray(list[i].children) && list[i].children.length > 0) {
            this.updateName(list[i].children, id, name)
          }
        }
      },
      /**
       * @description: 焦点值
       * @param {string} key 字段名
       * @param {string} value 字段值
       * @return {void}
       */
      saveFocusValue(key, value) {
        this.focusValue = {
          key,
          value
        }
      },
      /**
       * @description: 编辑
       * @param {object} row 行数据
       * @param {boolean} refresh 需要刷新
       * @param {string} blurIndex 失焦字段
       * @return {void}
       */
      async handleUpdate(row, refresh = false, blurIndex = '') {
        if (row.type === 0) {
          // 编辑阶段/类别
          // 失去焦点时值未改变
          if (this.focusValue.key === blurIndex) {
            // 时间格式
            if (row[blurIndex]?._isAMomentObject) {
              if (row[blurIndex].format('YYYY-MM-DD') === (this.focusValue.value?._isAMomentObject ? this.focusValue.value?.format('YYYY-MM-DD') : this.focusValue.value)) return
            } else {
              if (this.focusValue.value === row[blurIndex]) return
            }
          }
          const { id, name, parentId } = row
          this.updateName(this.tableData, id, name)
          // this.tableData = [...this.tableData]
          await monthPlanApi.updateNode({ id, name, parentId })
        } else {
          // 编辑业务事项
          if (blurIndex !== '') {
            // 失去焦点
  
            // 失去焦点时值未改变
            if (this.focusValue.key === blurIndex) {
              // 时间格式
              if (row[blurIndex]?._isAMomentObject) {
                if (row[blurIndex].format('YYYY-MM-DD') === (this.focusValue.value?._isAMomentObject ? this.focusValue.value?.format('YYYY-MM-DD') : this.focusValue.value)) return
              } else {
                if (this.focusValue.value === row[blurIndex]) return
              }
            }
          } else {
            // 其他情况loading
            this.loading = true
          }
          const {
            id,
            name,
            businessMatters,
            controlLevel,
            duration,
            startDate,
            endDate,
            completeStandard,
            verifyFiles,
            firstResId,
            firstResName,
            perList
          } = row
          const { code } = await monthPlanApi.updateNode({
            id,
            name: businessMatters,
            controlLevel,
            duration,
            startDate: this.formatDate(startDate, false),
            endDate: this.formatDate(endDate, false),
            completeStandard,
            verifyFiles,
            firstResId,
            firstResName,
            perList,
            selectId: this.selectRow.id,
          })
          this.loading = false
          if (code !== 200) {
            this.$message.warning('编辑失败')
            if (refresh) {
              this.loadData()
            }
          } else {
            // 刷新表格
            if (refresh) {
              this.loadData()
              this.selectRow = {}
            }
          }
        }
      },
      /**
       * @description: 选择第一责任人
       * @param {object} row 当前行数据
       * @return {void}
       */
      handleFirstResNameSelect(row) {
        this.firstResNameData.row = row
        this.firstResNameVisible = true
      },
      /**
       * @description: 选择第一责任人回调
       * @param {object} value 选中项数据
       * @return {void}
       */
      handleFirstResName(value) {
        this.firstResNameData.row.firstResId = value.jobsSelectedId
        this.firstResNameData.row.firstResName = value.jobsSelectedName
        this.firstResNameVisible = false
        this.handleUpdate(this.firstResNameData.row, false, 'firstResName')
      },
      /**
       * @description: 展开全部
       * @return {void}
       */    
      allTreeExpansion(){
        if(!this.isAudit && !this.isDetail){
          this.loadData()
        }
        this.$refs.table.setAllTreeExpansion()
      },
    }
  }
  </script>
  <style lang="less">
  .row-active {
    background-color: #e6f7ff;
  }
  </style>
  <style lang="less" scoped>
  @deep: ~'>>>';
  .title-wrapper {
    display: flex;
    > button {
      margin-left: 6px;
      &:first-of-type {
        margin-left: auto;
      }
    }
  }
  .icon-item {
    margin-right: 8px;
    font-size: 15px;
  }
  @{deep} .plTableBox .el-table td {
    padding: 2px 0;
    height: 40px !important;
  }
  @{deep} .plTableBox .el-table th {
    padding: 8px 0;
  }
  .btn-wrapper {
    margin: 0 -5px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    button {
      margin: 3px;
    }
  }
  .pub-table-select-count {
    margin-top: 5px;
    > span {
      margin-right: 12px;
    }
  }
  .width-100 {
    width: 100%;
  }
  @{deep} .week-plan-view-table .el-table td .cell {
    overflow: visible;
    .ant-select-auto-complete.ant-select .ant-input[disabled] {
      color: #555;
    }
  }
  .span-ellipsis {
    width: 100%;
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-all;
  }
  .span-btn-ellipsis {
    width: 100%;
    display: flex;
    justify-content: center;
  }
  .span-btn-ellipsis-text {
    width: calc(100% - 85px);
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-all;
  }
  .span-btn-ellipsis-btn {
    width: 75px;
    margin-left: 10px;
  }
  .week-plan-view-search {
    margin-bottom: 7px;
    @{deep}.ant-form-item .ant-form-item-label {
      width: 0;
    }
    @{deep} .ant-form-item .ant-form-item-control-wrapper {
      width: 100%;
    }
  }
  .week-plan-view-search-width {
    width: 200px;
  }
  .week-plan-view-search-date {
    width: 268px;
  }
  .activity-on-arrow {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    .wrapper {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
    }
  }

  @{deep} .BaseInputNumber-container input {
    text-align: center;
  }
  </style>
  